<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

/**
 * ThinkPHP标签库TagLib解析基类
 * @category   Think
 * @package  Think
 * @subpackage  Template
 * @author    liu21st <liu21st@gmail.com>
 */
class TagLib {

	/**
	 * 标签库定义XML文件
	 * @var string
	 * @access protected
	 */
	protected $xml      = '';
	protected $tags     = array();// 标签定义
	/**
	 * 标签库名称
	 * @var string
	 * @access protected
	 */
	protected $tagLib   ='';

	/**
	 * 标签库标签列表
	 * @var string
	 * @access protected
	 */
	protected $tagList  = array();

	/**
	 * 标签库分析数组
	 * @var string
	 * @access protected
	 */
	protected $parse    = array();

	/**
	 * 标签库是否有效
	 * @var string
	 * @access protected
	 */
	protected $valid    = false;

	/**
	 * 当前模板对象
	 * @var object
	 * @access protected
	 */
	protected $tpl;

	protected $comparison = array(' nheq '=>' !== ',' heq '=>' === ',' neq '=>' != ',' eq '=>' == ',' egt '=>' >= ',' gt '=>' > ',' elt '=>' <= ',' lt '=>' < ');

	/**
	 * 架构函数
	 * @access public
	 */
	public function __construct() {
		$this->tagLib  = strtolower(substr(get_class($this),6));
		$this->tpl     = Think::instance('ThinkTemplate');
	}

	/**
	 * TagLib标签属性分析 返回标签属性数组
	 * @access public
	 * @param string $tagStr 标签内容
	 * @return array
	 */
	public function parseXmlAttr($attr,$tag) {
		//XML解析安全过滤
		$attr   =   str_replace('&','___', $attr);
		$xml    =   '<tpl><tag '.$attr.' /></tpl>';
		$xml    =   simplexml_load_string($xml);
		if(!$xml) {
			throw_exception(L('_XML_TAG_ERROR_').' : '.$attr);
		}
		$xml    =   (array)($xml->tag->attributes());
		$array  =   array_change_key_case($xml['@attributes']);
		if($array) {
			$attrs  = explode(',',$this->tags[strtolower($tag)]['attr']);
			if(isset($this->tags[strtolower($tag)]['must'])){
				$must   =   explode(',',$this->tags[strtolower($tag)]['must']);
			}else{
				$must   =   array();
			}
			foreach($attrs as $name) {
				if( isset($array[$name])) {
					$array[$name] = str_replace('___','&',$array[$name]);
				}elseif(false !== array_search($name,$must)){
					throw_exception(L('_PARAM_ERROR_').':'.$name);
				}
			}
			return $array;
		}
	}

	/**
	 * 解析条件表达式
	 * @access public
	 * @param string $condition 表达式标签内容
	 * @return array
	 */
	public function parseCondition($condition) {
		$condition = str_ireplace(array_keys($this->comparison),array_values($this->comparison),$condition);
		$condition = preg_replace('/\$(\w+):(\w+)\s/is','$\\1->\\2 ',$condition);
		switch(strtolower(C('TMPL_VAR_IDENTIFY'))) {
			case 'array': // 识别为数组
				$condition  =   preg_replace('/\$(\w+)\.(\w+)\s/is','$\\1["\\2"] ',$condition);
				break;
			case 'obj':  // 识别为对象
				$condition  =   preg_replace('/\$(\w+)\.(\w+)\s/is','$\\1->\\2 ',$condition);
				break;
			default:  // 自动判断数组或对象 只支持二维
				$condition  =   preg_replace('/\$(\w+)\.(\w+)\s/is','(is_array($\\1)?$\\1["\\2"]:$\\1->\\2) ',$condition);
		}
		if(false !== strpos($condition, '$Think'))
		$condition      =   preg_replace('/(\$Think.*?)\s/ies',"\$this->parseThinkVar('\\1');" , $condition);
		return $condition;
	}

	/**
	 * 自动识别构建变量
	 * @access public
	 * @param string $name 变量描述
	 * @return string
	 */
	public function autoBuildVar($name) {
		if('Think.' == substr($name,0,6)){
			// 特殊变量
			return $this->parseThinkVar($name);
		}elseif(strpos($name,'.')) {
			$vars = explode('.',$name);
			$var  =  array_shift($vars);
			switch(strtolower(C('TMPL_VAR_IDENTIFY'))) {
				case 'array': // 识别为数组
					$name = '$'.$var;
					foreach ($vars as $key=>$val){
						if(0===strpos($val,'$')) {
							$name .= '["{'.$val.'}"]';
						}else{
							$name .= '["'.$val.'"]';
						}
					}
					break;
				case 'obj':  // 识别为对象
					$name = '$'.$var;
					foreach ($vars as $key=>$val)
					$name .= '->'.$val;
					break;
				default:  // 自动判断数组或对象 只支持二维
					$name = 'is_array($'.$var.')?$'.$var.'["'.$vars[0].'"]:$'.$var.'->'.$vars[0];
			}
		}elseif(strpos($name,':')){
			// 额外的对象方式支持
			$name   =   '$'.str_replace(':','->',$name);
		}elseif(!defined($name)) {
			$name = '$'.$name;
		}
		return $name;
	}

	/**
	 * 用于标签属性里面的特殊模板变量解析
	 * 格式 以 Think. 打头的变量属于特殊模板变量
	 * @access public
	 * @param string $varStr  变量字符串
	 * @return string
	 */
	public function parseThinkVar($varStr){
		$vars       = explode('.',$varStr);
		$vars[1]    = strtoupper(trim($vars[1]));
		$parseStr   = '';
		if(count($vars)>=3){
			$vars[2] = trim($vars[2]);
			switch($vars[1]){
				case 'SERVER':    $parseStr = '$_SERVER[\''.$vars[2].'\']';break;
				case 'GET':         $parseStr = '$_GET[\''.$vars[2].'\']';break;
				case 'POST':       $parseStr = '$_POST[\''.$vars[2].'\']';break;
				case 'COOKIE':
					if(isset($vars[3])) {
						$parseStr = '$_COOKIE[\''.$vars[2].'\'][\''.$vars[3].'\']';
					}elseif(C('COOKIE_PREFIX')){
						$parseStr = '$_COOKIE[\''.C('COOKIE_PREFIX').$vars[2].'\']';
					}else{
						$parseStr = '$_COOKIE[\''.$vars[2].'\']';
					}
					break;
				case 'SESSION':
					if(isset($vars[3])) {
						$parseStr = '$_SESSION[\''.$vars[2].'\'][\''.$vars[3].'\']';
					}elseif(C('SESSION_PREFIX')){
						$parseStr = '$_SESSION[\''.C('SESSION_PREFIX').'\'][\''.$vars[2].'\']';
					}else{
						$parseStr = '$_SESSION[\''.$vars[2].'\']';
					}
					break;
				case 'ENV':         $parseStr = '$_ENV[\''.$vars[2].'\']';break;
				case 'REQUEST':  $parseStr = '$_REQUEST[\''.$vars[2].'\']';break;
				case 'CONST':     $parseStr = strtoupper($vars[2]);break;
				case 'LANG':       $parseStr = 'L("'.$vars[2].'")';break;
				case 'CONFIG':    $parseStr = 'C("'.$vars[2].'")';break;
			}
		}else if(count($vars)==2){
			switch($vars[1]){
				case 'NOW':       $parseStr = "date('Y-m-d g:i a',time())";break;
				case 'VERSION':  $parseStr = 'THINK_VERSION';break;
				case 'TEMPLATE':$parseStr = 'C("TEMPLATE_NAME")';break;
				case 'LDELIM':    $parseStr = 'C("TMPL_L_DELIM")';break;
				case 'RDELIM':    $parseStr = 'C("TMPL_R_DELIM")';break;
				default:  if(defined($vars[1])) $parseStr = $vars[1];
			}
		}
		return $parseStr;
	}

	// 获取标签定义
	public function getTags(){
		return $this->tags;
	}
}